package com.syh.jn.scm.infrastructure.repository.impl.supplier.sale;

import cn.redscarf.commons.util.bean.ExtBeanUtils;
import cn.redscarf.commons.util.other.ExtStringUtils;
import cn.redscarf.commons.wrapper.Restrictions;
import cn.redscarf.commons.wrapper.Wrapper;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.syh.core.ddd.infrastructure.repository.AbstractAggregateRepository;
import com.syh.core.ddd.infrastructure.repository.AggregateRepoHibernateImplTmpl;
import com.syh.core.expction.DataModelException;
import com.syh.jn.scm.domain.supplier.entity.sale.SaleOrder;
import com.syh.jn.scm.domain.supplier.entity.sale.SaleOrderItem;
import com.syh.jn.scm.domain.supplier.repository.logistics.LogisticsBillReadRepository;
import com.syh.jn.scm.domain.supplier.repository.sale.SaleOrderRepository;
import com.syh.jn.scm.dto.supplier.sale.SaleOrderItemVo;
import com.syh.jn.scm.dto.supplier.sale.SaleOrderVo;
import com.syh.jn.scm.dto.supplier.sale.SaleStatisticalAmountVo;
import com.syh.jn.scm.exception.BusinessException;
import com.syh.jn.scm.infrastructure.repository.model.base.goods.GoodsBrandModel;
import com.syh.jn.scm.infrastructure.repository.model.base.goods.GoodsCategoryModel;
import com.syh.jn.scm.infrastructure.repository.model.base.goods.GoodsModel;
import com.syh.jn.scm.infrastructure.repository.model.sale.SaleOrderItemModel;
import com.syh.jn.scm.infrastructure.repository.model.sale.SaleOrderModel;
import com.syh.jn.scm.infrastructure.repository.utils.MybatisTemplate;
import com.syh.jn.scm.infrastructure.repository.utils.SQLAliasGenerateUtil;
import com.syh.jn.scm.infrastructure.wrapper.BaseResolve;
import com.syh.jn.scm.infrastructure.wrapper.ResolveToSQL;
import org.apache.ibatis.jdbc.SQL;
import org.hibernate.Query;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.orm.hibernate5.HibernateTemplate;
import org.springframework.stereotype.Repository;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Date:2018/7/16
 * Author:Clown
 * Desc;
 */
@Repository
public class SaleOrderRepositoryImpl implements SaleOrderRepository {

  private HibernateTemplate hibernateTemplate;

  private AggregateRepoHibernateImplTmpl<SaleOrder,SaleOrderModel,Long> saleOrderRepoHibernateImpl;
  private AggregateRepoHibernateImplTmpl<SaleOrderItem,SaleOrderItemModel,Long> saleOrderItemRepoHibernateImpl;

  @Autowired
  public SaleOrderRepositoryImpl(HibernateTemplate hibernateTemplate) {
    this.hibernateTemplate = hibernateTemplate;
    this.saleOrderRepoHibernateImpl =
            new AggregateRepoHibernateImplTmpl.Builder().hibernateTemplate(this.hibernateTemplate).entityClass(SaleOrder.class).modelClass(SaleOrderModel.class).idClass(Long.class).build();
    this.saleOrderItemRepoHibernateImpl =
            new AggregateRepoHibernateImplTmpl.Builder().hibernateTemplate(this.hibernateTemplate).entityClass(SaleOrderItem.class).modelClass(SaleOrderItemModel.class).idClass(Long.class).build();
  }


  /**
   * 增加
   *
   * @param saleOrder
   * @return
   */
  @Override
  public Long add(SaleOrder saleOrder) {
    SaleOrderModel saleOrderModel = this.saleOrderRepoHibernateImpl.add(saleOrder);
    this.saveOrderItems(saleOrderModel.getId(), saleOrder.getItems());
    return saleOrderModel.getId();
  }

  /**
   * 修改
   *
   * @param saleOrder
   */
  @Override
  public void update(SaleOrder saleOrder) {
    this.saleOrderRepoHibernateImpl.update(saleOrder);
    this.removeItem(saleOrder.getId());
    this.saveOrderItems(saleOrder.getId(), saleOrder.getItems());
  }


  /**
   * 修改状态
   */
  public void updateStatus(SaleOrder saleOrder) {
    this.saleOrderRepoHibernateImpl.update(saleOrder);
  }

  /**
   * 删除订单项
   *
   * @param id 订单id
   */
  private void removeItem(Long id) {
    StringBuffer hql = new StringBuffer();
    hql.append("from SaleOrderItemModel model where model.saleOrderId = ?");
    List<SaleOrderItemModel> itemModelList = (List<SaleOrderItemModel>) this.hibernateTemplate.find(hql.toString(), id);
    itemModelList.stream().forEach(item -> {
      this.hibernateTemplate.delete(item);
    });
  }

  @Override
  public void removeById(Long id) {
    this.removeItem(id);
    this.saleOrderRepoHibernateImpl.removeById(id);
  }

  /**
   * 删除
   *
   * @param saleOrder
   */
  @Override
  public void remove(SaleOrder saleOrder) {
    this.removeById(saleOrder.getId());
  }

  @Override
  public SaleOrder getById(Long id) {
    SaleOrder order = this.saleOrderRepoHibernateImpl.getById(id);
    if (order == null) {
      return order;
    }
    order.setItems(getItemsBySaleOrderId(id));
    return order;
  }


  public SaleOrder getOne(Wrapper wrapper) {
    SaleOrder saleOrder = saleOrderRepoHibernateImpl.getOne(wrapper);
    saleOrder.setItems(this.getItemsBySaleOrderId(saleOrder.getId()));
    return saleOrder;
  }

  /**
   * 根据订单id获取明细
   *
   * @param saleOrderId
   * @return
   */
  @Override
  public List<SaleOrderItem> getItemsBySaleOrderId(Long saleOrderId) {
    Wrapper wrapper = Wrapper.build().append(Restrictions.eq("saleOrderId",saleOrderId));
    List<SaleOrderItem> saleOrderItems = this.saleOrderItemRepoHibernateImpl.getList(wrapper);
    return saleOrderItems;
  }

  /**
   * 根据明细id获取明细
   *
   * @param id
   * @return
   */
  @Override
  public SaleOrderItem getItemByItemId(Long id) {
    return this.saleOrderItemRepoHibernateImpl.getById(id);
  }

  /**
   * 根据ids获取明细
   *
   * @param saleOrderIds
   * @return
   */
  @Override
  public List<SaleOrderItem> getItemsBySaleOrderIds(Long[] saleOrderIds) {
    Wrapper wrapper = Wrapper.build().append(Restrictions.in("saleOrderId",saleOrderIds));
    List<SaleOrderItem> saleOrderItems = this.saleOrderItemRepoHibernateImpl.getList(wrapper);
    return saleOrderItems;
  }

  /**
   * 根据商品id拿到订单明细对象
   *
   * @param goodsId
   * @return
   */
  @Override
  public SaleOrderItem getByGoodsId(Long goodsId, Long id) {
    Wrapper wrapper = Wrapper.build().append(Restrictions.eq("goodsId",goodsId)).append(Restrictions.eq("id",id));
    SaleOrderItem item = this.saleOrderItemRepoHibernateImpl.getOne(wrapper);
    return item;
  }

  /**
   * 上传单据图片
   *
   * @param order
   */
  @Override
  public void upload(SaleOrder order) {
    this.saleOrderRepoHibernateImpl.update(order);
  }

  /**
   * 根据服务商id删除订单
   * @param businessEntityId
   */
  @Override
  public void deleteByBusinessEntityId(Long businessEntityId) {
    String itemHql = "delete from SaleOrderItemModel where businessEntityId = :businessEntityId";
    Query itemQuery = this.hibernateTemplate.getSessionFactory().getCurrentSession().createQuery(itemHql);
    itemQuery.setParameter("businessEntityId",businessEntityId);
    itemQuery.executeUpdate();
    String orderHql = "delete from SaleOrderModel where businessEntityId = :businessEntityId";
    Query orderQuery = this.hibernateTemplate.getSessionFactory().getCurrentSession().createQuery(orderHql);
    orderQuery.setParameter("businessEntityId",businessEntityId);
    orderQuery.executeUpdate();
  }

  /**
   * 销售订单统计查询
   * @param wrapper
   * @return
   */
  @Override
  public SaleStatisticalAmountVo statisticalAmount(Wrapper wrapper) {
    return null;
  }

  @Override
  public SaleStatisticalAmountVo statisticalAmountByOrder(Wrapper we) {
    return null;
  }

  @Override
  public List<SaleStatisticalAmountVo> statisticalAmountByCustomer(Wrapper we) {
    return null;
  }

  @Override
  public List<SaleStatisticalAmountVo> statisticalAmountByGoods(Wrapper wrapper) {
    return null;
  }

  /**
   * 保存销售单对应的订单项
   *
   * @param id
   * @param items
   */
  private void saveOrderItems(Long id, List<SaleOrderItem> items) {
    items.stream().forEach(item -> {
      SaleOrderItemModel itemModel = new SaleOrderItemModel();
      GoodsModel goodsModel = this.hibernateTemplate.get(GoodsModel.class, item.getGoodsId());
      GoodsBrandModel goodsBrandModel = new GoodsBrandModel();
      if (goodsModel.getGoodsBrandId() != null) {
        goodsBrandModel = this.hibernateTemplate.get(GoodsBrandModel.class, goodsModel.getGoodsBrandId());
      }
      GoodsCategoryModel goodsCategoryModel = new GoodsCategoryModel();
      if (goodsModel.getCategoryId() != null) {
        goodsCategoryModel = this.hibernateTemplate.get(GoodsCategoryModel.class, goodsModel.getCategoryId());
      }
      SaleOrderModel saleOrderModel = this.hibernateTemplate.get(SaleOrderModel.class, id);

      ExtBeanUtils.copyProperties(item, itemModel);
      itemModel.setSaleOrderId(id);
      itemModel.setBusinessEntityId(saleOrderModel.getBusinessEntityId());
      //在仓储层冗余是为了安全和数据的准确
      itemModel.setGoodsName(goodsModel.getName());
      itemModel.setSpecName(goodsModel.getSpecName());
      itemModel.setGoodsCode(goodsModel.getCode());
      itemModel.setIsDefaultGoods(goodsModel.getIsDefaultGoods());
      itemModel.setConversionRate(goodsModel.getConversionRate());
      itemModel.setCodeBar(goodsModel.getCodeBar());
      itemModel.setUnits(goodsModel.getUnits());
      itemModel.setCategoryId(goodsModel.getCategoryId());
      itemModel.setCategoryName(goodsCategoryModel.getName());
      itemModel.setCategoryCatalogCode(goodsCategoryModel.getCatalogCode());
      itemModel.setGoodsBrandId(ExtStringUtils.isBlank(goodsModel.getGoodsBrandId()) ? null : goodsModel.getGoodsBrandId());
      itemModel.setGoodsBrandName(ExtStringUtils.isBlank(goodsBrandModel.getName()) ? null : goodsBrandModel.getName());
      this.hibernateTemplate.save(itemModel);
    });
  }


  /**
   * 判断销售项是否存在该商品
   *
   * @param column
   * @param id
   * @return
   */
  @Override
  public boolean saleItemExistsById(String column, Long id) {
    Wrapper wrapper = Wrapper.build().append(Restrictions.eq(column,id));
    return this.saleOrderItemRepoHibernateImpl.getCount(wrapper) > 0;
  }

  /**
   * 更新发货信息
   *
   * @param order
   */
  @Override
  public void updateOrderAndItems(SaleOrder order) {
    if (this.saleOrderRepoHibernateImpl.getById(order.getId()) == null) {
      throw new DataModelException("订单不存在");
    }
    this.saleOrderRepoHibernateImpl.update(order);
    order.getItems().forEach(saleOrderItem -> {
      if (this.saleOrderItemRepoHibernateImpl.getById(saleOrderItem.getId()) == null) {
        throw new DataModelException("对应明细不存在");
      }
      this.saleOrderItemRepoHibernateImpl.update(saleOrderItem);
    });
  }

  /**
   * 内部方法  领域对象转vo
   * @param entityList
   * @return
   */
  private List<SaleOrderItemVo> transformSaleItems(List<SaleOrderItem> entityList) {
    List<SaleOrderItemVo> voList = new ArrayList<>();
    entityList.stream().forEach((entity) -> {
      SaleOrderItemVo vo = new SaleOrderItemVo();
      ExtBeanUtils.copyProperties(entity, vo);
      voList.add(vo);
    });
    return voList;
  }

  @Override
  public boolean contains(Long id) {
    return this.saleOrderRepoHibernateImpl.contains(id);
  }

  @Override
  public  List<SaleOrder> getList(Wrapper wrapper) {
    List<SaleOrder> saleOrders = this.saleOrderRepoHibernateImpl.getList(wrapper);
    return saleOrders;
  }

  @Override
  public List<SaleOrder> findListPage(Wrapper wrapper, Integer startRow, Integer count) {
    List<SaleOrder> saleOrders = this.saleOrderRepoHibernateImpl.findListPage(wrapper,startRow,count);
    return saleOrders;
  }

  @Override
  public int getCount(Wrapper wrapper) {
    int count = this.saleOrderRepoHibernateImpl.getCount(wrapper);
    return count;
  }
}
